//#ifndef _CONSOLE
#include "stdafx.h"
//#endif

#include "init.h"
#include <stdio.h>
#include "tinyxml.h"
#include <iostream>
#include <vector>

using namespace std;

int getConnectionConfig(connection_config * stConnConfig, rec_config * stRecConfig);
static const char * configFileName = "config.ini";

#define configXmlFile "config.xml"

#define NUM_FIELD 7

CConfig * CConfig::m_instance = NULL;

CConfig::CConfig()
{	
        connection_config stConnectConfig;
#ifdef _WIN32
		WSADATA wsaData;
		if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
		{
			printf("failed\n");
			return;
		}
#else

#endif
		memset(&m_recConfig, 0, sizeof(rec_config));
		int ret = getConnectionConfig(&stConnectConfig, &m_recConfig);
    if(ret == 0)
    {
        m_pstConnectionConfig = new connection_config;
        memcpy(m_pstConnectionConfig,&stConnectConfig,sizeof(connection_config));
    }
    else
    {
        m_pstConnectionConfig = NULL;
    }
}

CConfig * CConfig::getGlobleConfig(void)
{
     if(m_instance == NULL)
     {
    	 m_instance = new CConfig();
     }
     return m_instance;
}

connection_config* CConfig::getConnConfig(void)
{
    return m_pstConnectionConfig;
}

void CConfig::getRecConfig(rec_config * recThreOut)
{
	//strcpy_s(strBuff, m_picDbPath);
	//strcpy_s(strBuff, 128, m_picDbPath);

	memcpy(recThreOut, &m_recConfig, sizeof(rec_config));
}

CConfig::~CConfig()
{
   if(m_pstConnectionConfig)
   {
	   delete m_pstConnectionConfig;
	   m_pstConnectionConfig = NULL;
   }

   /*if(m_instance)
   {
       delete m_instance;
       m_instance = NULL;
   }*/
}

////
//get config info in one line string
////
int getConfigOneLine(char * strIn, connection_config * stConnConfigOut, rec_config * pstRecConfig)
{
	static const char * strRemoteIp = "remoteIp";
	static const char * strRemotePort = "remotePort";
	static const char * strLocalIp = "localIp";
	static const char * strLocalPort = "localPort";

	static const char * strPicDbPath = "picDb";

	static const char * strBinDataPath = "binData";

	static const char * strRecthreshold = "recThre";


	char * subStringStart = NULL;
	char * value = NULL;

	subStringStart = strstr(strIn,strRemoteIp);
	if(subStringStart)
	{
		struct in_addr tempInAddr;
		value = subStringStart +strlen(strRemoteIp) + 1;

//#ifdef _WIN32
//		stConnConfigOut->localAddr.sin_addr.s_addr = inet_addr(value);
//#else
		if (inet_pton(AF_INET, value, &tempInAddr) == 1)
		{
			stConnConfigOut->remoteAddr.sin_addr.s_addr = tempInAddr.s_addr;
			return 0;
		}
		else
		{
			return -1;
		}
	}

	subStringStart = strstr(strIn,strRemotePort);
	if(subStringStart)
	{
		uint16_t remotePort;
		value = subStringStart +strlen(strRemotePort) + 1;
		remotePort = (uint16_t)atoi(value);
		stConnConfigOut->remoteAddr.sin_port = htons(remotePort);

		return 0;
	}


	subStringStart = strstr(strIn,strLocalIp);
	if(subStringStart)
	{
		struct in_addr tempInAddr;
		value = subStringStart +strlen(strLocalIp) + 1;
//#ifdef _WIN32
//		stConnConfigOut->localAddr.sin_addr.s_addr = inet_addr(value);
//#else
		if (inet_pton(AF_INET, value, &tempInAddr) == 1)
		{
			stConnConfigOut->localAddr.sin_addr.s_addr = tempInAddr.s_addr;
			return 0;
		}
		else
		{
			return -1;
		}
//#endif	

	}

	subStringStart = strstr(strIn,strLocalPort);
	if(subStringStart)
	{
		uint16_t localPort;
		value = subStringStart + strlen(strLocalPort) + 1;
		localPort = (uint16_t)atoi(value);
		stConnConfigOut->localAddr.sin_port = htons(localPort);

		return 0;
	}

	subStringStart = strstr(strIn, strPicDbPath);
	if (subStringStart)
	{
		value = subStringStart + strlen(strPicDbPath) + 1;
		size_t valueLen = strlen(strIn) - strlen(strPicDbPath) - 1;
		memcpy(pstRecConfig->pathPicDb, value, valueLen);

		return 0;
	}

	subStringStart = strstr(strIn, strBinDataPath);
	if (subStringStart)
	{
		value = subStringStart + strlen(strBinDataPath) + 1;
		size_t valueLen = strlen(strIn) - strlen(strBinDataPath) - 1;
		memcpy(pstRecConfig->pathBindata, value, valueLen);

		return 0;
	}

	subStringStart = strstr(strIn, strRecthreshold);
	if (subStringStart)
	{
		value = subStringStart + strlen(strRecthreshold) + 1;
		pstRecConfig->recThreshold = (float)atof(value);
		return 0;
	}

	return 0;
}

/////////////////////////
//get the net config from config file
///////////////////////////
int getConnectionConfig1(connection_config * stConnConfig, rec_config  * pstRecConfig)
{
	char strOneLine[128] = {0};
    //char strIp[64] = {0};
    //unsigned char buffIp[4];

    FILE * fpConfig = NULL;

	fopen_s(&fpConfig, configFileName,"r");

    //fpConfig = fopen(configFileName,"r");
    if(fpConfig == NULL)
    {
    	printf("open config file failed\n");
    	return -1;
    }

    memset(&stConnConfig->localAddr,0, sizeof(struct sockaddr_in));
    memset(&stConnConfig->remoteAddr,0, sizeof(struct sockaddr_in));
    stConnConfig->localAddr.sin_family = AF_INET;
    stConnConfig->remoteAddr.sin_family = AF_INET;


    while(fgets(strOneLine,128,fpConfig))
    {
    	//printf("str one line: %s\n",strOneLine);
    	if((strOneLine[strlen(strOneLine)-1] == '\r')||(strOneLine[strlen(strOneLine)-1] == '\n'))
    	{
    		strOneLine[strlen(strOneLine)-1] = '\0';
    	}
		getConfigOneLine(strOneLine, stConnConfig, pstRecConfig);
    }

    //memcpy(buffIp,&stConnConfig->remoteAddr.sin_addr.s_addr,4);
    //inet_ntop(AF_INET,buffIp,strIp,INET_ADDRSTRLEN);
    //printf("remoteIp:%s  reomtePort:%d\n",strIp,ntohs(stConnConfig->remoteAddr.sin_port));
    //memset(strIp,0,64);
    //inet_ntop(AF_INET,(char*)&(stConnConfig->localAddr.sin_addr.s_addr),strIp,INET_ADDRSTRLEN);
   //printf("localIp:%s  localPort:%d\n",strIp,ntohs(stConnConfig->localAddr.sin_port));


    fclose(fpConfig);
    fpConfig = NULL;

    return 0;
}

int getConnectionConfig(connection_config * stConnConfigOut, rec_config  * pstRecConfig)
{
	TiXmlDocument doc("config.xml");
	bool loadOkay = doc.LoadFile();

	if (!loadOkay)
	{
		printf("Could not load test file 'demotest.xml'. Error='%s'. Exiting.\n", doc.ErrorDesc());
		return -1;
	}

	TiXmlNode* node = 0;
	TiXmlElement* configElement = 0;
	TiXmlElement* itemElement = 0;


	// --------------------------------------------------------
	// An example of changing existing attributes, and removing
	// an element from the document.
	// --------------------------------------------------------

	// Get the "ToDo" element.
	// It is a child of the document, and can be selected by name.
	node = doc.FirstChild("config");
	assert(node);
	configElement = node->ToElement();
	assert(configElement);

	// Going to the toy store is now our second priority...
	// So set the "priority" attribute of the first item in the list.
	node = configElement->FirstChildElement();	// This skips the "PDA" comment.
	assert(node);
	itemElement = node->ToElement();
	const char * strArr[NUM_FIELD] = {
		"remote_ip",
		"remote_port",
		"local_ip",
		"local_port",
		"pic_db",
		"bin_data",
		"rec_thre"
	};

	char flagArr[NUM_FIELD] = { 0,0,0,0,0,0,0 };

	int indexStr = 0;

	const char * p_field = NULL;
	const char * p_value = NULL;

	while (itemElement)
	{
		p_field = itemElement->Value();
		p_value = itemElement->GetText();
		printf("element is %s\n", itemElement->Value());
		printf("txt is %s\n", itemElement->GetText());
		indexStr = 0;
		while (indexStr < NUM_FIELD)
		{

			if (flagArr[indexStr] == 1)
			{
				indexStr++;
				continue;
			}
			
			if (strcmp(strArr[indexStr], p_field) == 0)
			{
				switch (indexStr)
				{
				case 0:
				{
					struct in_addr tempInAddr;

					//#ifdef _WIN32
					//		stConnConfigOut->localAddr.sin_addr.s_addr = inet_addr(value);
					//#else
					if (inet_pton(AF_INET, p_value, &tempInAddr) == 1)
					{
						stConnConfigOut->remoteAddr.sin_addr.s_addr = tempInAddr.s_addr;
					}
					else
					{
						printf("parse remote addr failed\n");
					}
				}
					break;
				case 1:
				{
				    uint16_t remotePort = (uint16_t)atoi(p_value);
					stConnConfigOut->remoteAddr.sin_port = htons(remotePort);
				}					
					break;
				case 2:
					struct in_addr tempInAddr;
					//#ifdef _WIN32
					//		stConnConfigOut->localAddr.sin_addr.s_addr = inet_addr(value);
					//#else
					if (inet_pton(AF_INET, p_value, &tempInAddr) == 1)
					{
						stConnConfigOut->localAddr.sin_addr.s_addr = tempInAddr.s_addr;
					}
					else
					{
						printf("parse local ip failed\n");
					}
					break;
				case 3:
					uint16_t localPort;
					localPort = (uint16_t)atoi(p_value);
					stConnConfigOut->localAddr.sin_port = htons(localPort);
					break;
				case 4:
					strcpy_s(pstRecConfig->pathPicDb, p_value);
					break;
				case 5:
					strcpy_s(pstRecConfig->pathBindata, p_value);
					break;
				case 6:
					pstRecConfig->recThreshold = (float)atof(p_value);
					break;
				default:
					break;
				}
				flagArr[indexStr] = 1;
			}
			indexStr++;
		}
		
		itemElement = itemElement->NextSiblingElement();

	}
	//assert( itemElement  );

	////itemElement->SetAttribute( "priority", 2 );

	//// Change the distance to "doing bills" from
	//// "none" to "here". It's the next sibling element.
	//itemElement = itemElement->NextSiblingElement();
	//assert( itemElement );
	//printf("second element is %s\n", itemElement->Value());
	//printf("second value is %s\n", itemElement->GetText());
	printf("parse ended\n");

	doc.Clear();

	return 0;


}




